<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>屏幕录制工具</title>
    <script src="./RecordRTC.js"></script>
    <!-- 添加ffmpeg.js -->
    <script src="https://cdn.bootcdn.net/ajax/libs/ffmpeg/0.11.6/ffmpeg.min.js"></script>
    <style>
      /* 保持原始样式不变，仅添加新元素的样式 */
      .recordings-panel {
        display: none;
        margin-top: 25px;
      }

      .recordings-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding-bottom: 15px;
        border-bottom: 1px solid var(--border-color);
      }

      .clear-btn {
        background: transparent;
        color: var(--text-primary);
        border: 1px solid var(--border-color);
        padding: 6px 12px;
        border-radius: 6px;
        cursor: pointer;
        font-size: 13px;
        transition: all 0.2s;
      }

      .clear-btn:hover {
        background: rgba(var(--btn-bg-rgb), 0.1);
      }

      .recordings-list {
        max-height: 300px;
        overflow-y: auto;
        margin-top: 15px;
      }

      .recording-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 12px 15px;
        margin-bottom: 10px;
        background: rgba(var(--border-color-rgb), 0.1);
        border-radius: 8px;
        border: 1px solid var(--border-color);
        transition: all 0.2s;
      }

      .recording-item:hover {
        background: rgba(var(--btn-bg-rgb), 0.1);
        transform: translateY(-2px);
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
      }

      .recording-info {
        display: flex;
        flex-direction: column;
      }

      .recording-title {
        font-weight: 500;
        margin-bottom: 5px;
      }

      .recording-meta {
        display: flex;
        font-size: 13px;
        color: #777;
      }

      .recording-meta span {
        margin-right: 15px;
      }

      .recording-controls {
        display: flex;
        gap: 8px;
      }

      .recording-btn {
        padding: 8px 12px;
        border-radius: 6px;
        border: none;
        cursor: pointer;
        font-size: 13px;
        transition: all 0.2s;
        display: flex;
        align-items: center;
      }

      .play-btn {
        background: #4a6cf7;
        color: white;
      }

      .download-btn {
        background: #34a853;
        color: white;
      }

      .download-mp4-btn {
        background: #ff9800;
        color: white;
      }

      .delete-btn {
        background: #ea4335;
        color: white;
      }

      .recording-btn i {
        margin-right: 5px;
        font-size: 14px;
      }

      .no-recordings {
        text-align: center;
        padding: 30px;
        color: #777;
        border: 1px dashed var(--border-color);
        border-radius: 8px;
      }

      /* 视频弹框样式 */
      .video-modal {
        display: none;
        position: fixed;
        z-index: 1000;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.8);
        justify-content: center;
        align-items: center;
      }

      .video-modal-content {
        position: relative;
        background-color: var(--card-bg);
        padding: 20px;
        border-radius: 12px;
        box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
        max-width: 90%;
        max-height: 90vh;
        display: flex;
        flex-direction: column;
      }

      .modal-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
      }

      .modal-title {
        font-weight: 600;
        font-size: 20px;
        color: var(--text-primary);
      }

      .close-modal {
        background: none;
        border: none;
        font-size: 28px;
        cursor: pointer;
        color: var(--text-primary);
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        transition: background-color 0.2s;
      }

      .close-modal:hover {
        background-color: rgba(var(--btn-bg-rgb), 0.1);
      }

      .modal-video-container {
        position: relative;
        width: 800px;
        max-width: 80vw;
        height: 0;
        padding-bottom: 56.25%;
        /* 16:9 aspect ratio */
      }

      .modal-video {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 8px;
      }

      .modal-info {
        margin-top: 15px;
        color: var(--text-primary);
        font-size: 14px;
      }

      /* 加载指示器 */
      .loading-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.7);
        z-index: 2000;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        color: white;
        font-size: 18px;
      }

      .spinner {
        width: 40px;
        height: 40px;
        border: 4px solid rgba(255, 255, 255, 0.3);
        border-radius: 50%;
        border-top: 4px solid #fff;
        animation: spin 1s linear infinite;
        margin-bottom: 15px;
      }

      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }

        100% {
          transform: rotate(360deg);
        }
      }

      /* 简约层叠风格CSS变量 */
      :root {
        --glass-bg: #fff;
        --bg-primary: #f8fafc;
        --bg-secondary: #ffffff;
        --text-primary: #1a202c;
        --text-secondary: #64748b;
        --btn-bg: #3b82f6;
        --btn-hover-bg: #2563eb;
        --btn-text: white;
        --border-color: #e2e8f0;
        --card-bg: #ffffff;
        --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        --btn-bg-rgb: 59, 130, 246;
        --border-color-rgb: 226, 232, 240;
        --accent-color: #10b981;
        --warning-color: #f59e0b;
        --danger-color: #ef4444;
        --layer-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
          0 2px 4px -1px rgba(0, 0, 0, 0.06);
        --layer-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
          0 4px 6px -2px rgba(0, 0, 0, 0.05);
      }

      .dark-theme {
        --bg-primary: #0f172a;
        --bg-secondary: #1e293b;
        --text-primary: #f1f5f9;
        --text-secondary: #94a3b8;
        --btn-bg: #3b82f6;
        --btn-hover-bg: #2563eb;
        --border-color: #334155;
        --card-bg: #1e293b;
        --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
        --border-color-rgb: 51, 65, 85;
        --layer-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3),
          0 2px 4px -1px rgba(0, 0, 0, 0.2);
        --layer-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.3),
          0 4px 6px -2px rgba(0, 0, 0, 0.2);
      }

      body {
        background: var(--bg-primary);
        color: var(--text-primary);
        font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
        max-width: 1200px;
        margin: 0 auto;
        padding: 24px;
        transition: all 0.3s ease;
        line-height: 1.6;
        min-height: 100vh;
      }

      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 32px;
        padding: 24px 32px;
        background: var(--card-bg);
        border: 1px solid var(--border-color);
        border-radius: 12px;
        box-shadow: var(--layer-shadow);
        position: relative;
        z-index: 10;
      }

      h1 {
        margin: 0;
        font-size: 24px;
        font-weight: 600;
        color: var(--text-primary);
      }

      .theme-toggle {
        background: var(--btn-bg);
        color: var(--btn-text);
        border: none;
        padding: 10px 16px;
        border-radius: 8px;
        cursor: pointer;
        font-size: 14px;
        font-weight: 500;
        transition: all 0.2s ease;
        box-shadow: var(--card-shadow);
      }

      .theme-toggle:hover {
        background: var(--btn-hover-bg);
        transform: translateY(-1px);
        box-shadow: var(--layer-shadow);
      }

      .card {
        background: var(--card-bg);
        border: 1px solid var(--border-color);
        border-radius: 12px;
        padding: 24px;
        margin: 20px 0;
        box-shadow: var(--card-shadow);
        transition: all 0.2s ease;
        position: relative;
      }

      .card:hover {
        transform: translateY(-2px);
        box-shadow: var(--layer-shadow-lg);
      }

      .card:nth-child(even) {
        transform: translateX(8px);
      }

      .card:nth-child(odd) {
        transform: translateX(-8px);
      }

      .card:nth-child(even):hover {
        transform: translateX(8px) translateY(-2px);
      }

      .card:nth-child(odd):hover {
        transform: translateX(-8px) translateY(-2px);
      }

      .card-title {
        font-size: 18px;
        font-weight: 600;
        margin-bottom: 15px;
        display: flex;
        align-items: center;
      }

      .card-title i {
        margin-right: 10px;
        font-size: 20px;
      }

      #videoPreview {
        width: 100%;
        background: #000;
        border-radius: 8px;
        margin-top: 10px;
        display: none;
      }

      .controls {
        display: flex;
        gap: 12px;
        margin: 20px 0;
        flex-wrap: wrap;
      }

      .btn {
        background: var(--btn-bg);
        color: var(--btn-text);
        border: none;
        padding: 12px 20px;
        border-radius: 8px;
        cursor: pointer;
        font-size: 14px;
        font-weight: 500;
        transition: all 0.2s ease;
        flex: 1;
        min-width: 120px;
        text-align: center;
        display: flex;
        justify-content: center;
        align-items: center;
        box-shadow: var(--card-shadow);
      }

      .btn:hover:not(:disabled) {
        background: var(--btn-hover-bg);
        transform: translateY(-1px);
        box-shadow: var(--layer-shadow);
      }

      .btn i {
        margin-right: 8px;
        font-size: 16px;
      }

      .btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
        transform: none;
        box-shadow: var(--card-shadow);
      }

      #recordedVideo {
        width: 100%;
        border-radius: 8px;
        background: #000;
        display: none;
        margin-top: 20px;
      }

      .status {
        margin-top: 16px;
        padding: 12px 16px;
        border-radius: 8px;
        text-align: center;
        background: var(--bg-secondary);
        border: 1px solid var(--border-color);
        font-size: 14px;
        color: var(--text-secondary);
      }

      .row {
        display: flex;
        gap: 24px;
        position: relative;
      }

      .col {
        flex: 1;
        position: relative;
      }

      .col:first-child {
        z-index: 2;
      }

      .col:last-child {
        z-index: 1;
      }

      .recorded-video-container {
        display: none;
      }

      .preview-container {
        position: relative;
      }

      .recording-indicator {
        position: absolute;
        top: 16px;
        right: 16px;
        background: var(--danger-color);
        color: white;
        padding: 6px 12px;
        border-radius: 6px;
        font-size: 12px;
        font-weight: 500;
        display: none;
        animation: pulse 1.5s infinite;
        box-shadow: var(--card-shadow);
      }

      @keyframes pulse {
        0% {
          opacity: 1;
        }

        50% {
          opacity: 0.7;
        }

        100% {
          opacity: 1;
        }
      }

      .icon {
        display: inline-block;
        width: 20px;
        height: 20px;
        background-size: contain;
        margin-right: 8px;
        vertical-align: middle;
      }

      .record-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M12 2C6.48 E 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z'/%3E%3Ccircle cx='12' cy='12' r='5' fill='red'/%3E%3C/svg%3E");
      }

      .stop-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Crect x='6' y='6' width='12' height='12' rx='1' fill='white'/%3E%3C/svg%3E");
      }

      .download-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z'/%3E%3C/svg%3E");
      }

      .play-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E");
      }

      /* 浮动按钮容器 */
      .fab-container {
        position: fixed;
        bottom: 30px;
        right: 30px;
        z-index: 1000;
        display: flex;
        flex-direction: column-reverse;
        align-items: flex-end;
        gap: 15px;
      }

      /* 主按钮样式 */
      .fab-main {
        width: 56px;
        height: 56px;
        border-radius: 50%;
        background: var(--btn-bg);
        color: var(--btn-text);
        border: none;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s ease;
      }

      .fab-main:hover {
        background: var(--btn-hover-bg);
        transform: scale(1.05);
        box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
      }

      /* 菜单容器 */
      .fab-menu {
        display: flex;
        flex-direction: column;
        gap: 12px;
        opacity: 0;
        transform: translateY(20px);
        pointer-events: none;
        transition: all 0.3s ease;
      }

      .fab-container.active .fab-menu {
        opacity: 1;
        transform: translateY(0);
        pointer-events: all;
      }

      /* 子菜单项 */
      .fab-item {
        width: 56px;
        height: 56px;
        border-radius: 50%;
        background: var(--card-bg);
        color: var(--text-primary);
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        transition: all 0.2s ease;
        position: relative;
      }

      .fab-item:hover {
        transform: translateY(-3px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      }

      .fab-item::after {
        content: attr(title);
        position: absolute;
        right: 50px;
        white-space: nowrap;
        background: var(--card-bg);
        color: var(--text-primary);
        padding: 6px 12px;
        border-radius: 4px;
        font-size: 13px;
        opacity: 0;
        pointer-events: none;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        transition: opacity 0.2s ease;
      }

      .fab-item:hover::after {
        opacity: 1;
      }

      /* 授权弹框样式 */
      .auth-modal {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(10px);
        z-index: 2000;
        justify-content: center;
        align-items: center;
        animation: fadeIn 0.3s ease;
      }

      @keyframes fadeIn {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      @keyframes slideUp {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .auth-modal-content {
        background: var(--glass-bg);
        backdrop-filter: blur(20px);
        border: 1px solid var(--glass-border);
        border-radius: 25px;
        padding: 40px;
        max-width: 450px;
        width: 90%;
        text-align: center;
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
        animation: slideUp 0.3s ease;
        position: relative;
        overflow: hidden;
      }

      .auth-modal-content::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 1px;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.4),
          transparent
        );
      }

      .auth-step-indicator {
        display: flex;
        justify-content: center;
        margin-bottom: 30px;
        gap: 15px;
      }

      .step-dot {
        width: 12px;
        height: 12px;
        border-radius: 50%;
        background: var(--border-color);
        transition: all 0.3s ease;
      }

      .step-dot.active {
        background: var(--accent-color);
        transform: scale(1.2);
        box-shadow: 0 0 20px rgba(16, 185, 129, 0.4);
      }

      .auth-icon {
        width: 80px;
        height: 80px;
        margin: 0 auto 25px;
        background: var(--accent-color);
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3);
      }

      .auth-icon svg {
        width: 40px;
        height: 40px;
        color: white;
      }

      .auth-title {
        font-size: 24px;
        font-weight: 700;
        margin-bottom: 15px;
        color: #333;
      }

      .auth-description {
        font-size: 16px;
        color: var(--text-secondary);
        margin-bottom: 30px;
        line-height: 1.6;
      }

      .auth-buttons {
        display: flex;
        gap: 15px;
        justify-content: center;
      }

      .auth-btn {
        padding: 14px 28px;
        border: none;
        border-radius: 15px;
        font-size: 16px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.3s ease;
        min-width: 120px;
        position: relative;
        overflow: hidden;
      }

      .auth-btn-primary {
        background: var(--accent-color);
        color: white;
        box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
      }

      .auth-btn-primary:hover {
        background: #059669;
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
      }

      .auth-btn-secondary {
        background: transparent;
        color: var(--text-secondary);
        border: 2px solid var(--border-color);
      }

      .auth-btn-secondary:hover {
        background: var(--glass-bg);
        color: var(--text-primary);
        border-color: var(--text-secondary);
        transform: translateY(-2px);
      }

      /* 麦克风和屏幕图标 */
      .mic-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M12 2a3 3 0 0 1 3 3v6a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z'/%3E%3Cpath d='M19 10v1a7 7 0 0 1-14 0v-1'/%3E%3Cpath d='M12 18v4'/%3E%3Cpath d='M8 22h8'/%3E%3C/svg%3E");
      }

      .screen-icon {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Crect x='2' y='3' width='20' height='14' rx='2' ry='2'/%3E%3Cline x1='8' y1='21' x2='16' y2='21'/%3E%3Cline x1='12' y1='17' x2='12' y2='21'/%3E%3C/svg%3E");
      }

      /* macOS权限说明样式 */
      .macos-permission-notice {
        background: linear-gradient(
          135deg,
          rgba(255, 149, 0, 0.1),
          rgba(255, 59, 48, 0.1)
        );
        border: 1px solid rgba(255, 149, 0, 0.3);
        border-radius: 12px;
        padding: 20px;
        margin: 20px 0;
        animation: fadeInUp 0.5s ease-out;
      }

      .notice-header {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-bottom: 15px;
        color: #ff9500;
        font-weight: 600;
      }

      .apple-icon {
        font-size: 20px;
        filter: drop-shadow(0 2px 4px rgba(255, 149, 0, 0.3));
      }

      .notice-content {
        color: var(--text-secondary);
        line-height: 1.6;
      }

      .notice-content p {
        margin: 10px 0;
      }

      .notice-content ol {
        margin: 15px 0;
        padding-left: 20px;
      }

      .notice-content li {
        margin: 8px 0;
        color: var(--text-primary);
        text-align: left;
      }

      .notice-content strong {
        color: #ff9500;
        font-weight: 600;
      }

      .notice-tip {
        background: rgba(255, 149, 0, 0.1);
        border-left: 3px solid #ff9500;
        padding: 10px 15px;
        margin: 15px 0 5px 0;
        border-radius: 0 8px 8px 0;
        font-size: 14px;
        color: var(--text-primary);
      }

      @keyframes fadeInUp {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }
    </style>
  </head>

  <body>
    <div class="fab-container">
      <button class="fab-main" id="fabMain">
        <svg
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" />
        </svg>
      </button>

      <div class="fab-menu">
        <a
          href="https://tinypng.com/"
          class="fab-item"
          target="_blank"
          title="图片压缩"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 48 48"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M10 38V44H38V38"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M38 20V14L30 4H10V20"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M28 4V14H38"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M16 12H20"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <rect
              x="4"
              y="20"
              width="40"
              height="18"
              rx="2"
              stroke="#333"
              stroke-width="4"
              stroke-linejoin="round"
            />
            <path
              d="M11 25H17L11 33H17"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M24 25V33"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <path
              d="M31 25V33"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <path
              d="M31 25H34.5C35.8807 25 37 26.1193 37 27.5V27.5C37 28.8807 35.8807 30 34.5 30H31"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
        </a>
        <a
          href="https://www.996day.com/imgFormat.html"
          target="_blank"
          class="fab-item"
          title="图片转换"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 48 48"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <rect
              x="6"
              y="22"
              width="20"
              height="20"
              rx="3"
              stroke="#333"
              stroke-width="4"
              stroke-linejoin="round"
            />
            <path
              d="M30 6L42 6L42 18"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <circle cx="34" cy="42" r="1.5" fill="#333" stroke="#333" />
            <circle
              r="1.5"
              transform="matrix(1 0 0 -1 6 14)"
              fill="#333"
              stroke="#333"
            />
            <circle cx="42" cy="42" r="1.5" fill="#333" stroke="#333" />
            <circle
              r="1.5"
              transform="matrix(1 0 0 -1 6 6)"
              fill="#333"
              stroke="#333"
            />
            <circle cx="42" cy="34" r="1.5" fill="#333" stroke="#333" />
            <circle
              r="1.5"
              transform="matrix(1 0 0 -1 14 6)"
              fill="#333"
              stroke="#333"
            />
            <circle cx="42" cy="26" r="1.5" fill="#333" stroke="#333" />
            <circle
              r="1.5"
              transform="matrix(1 0 0 -1 22 6)"
              fill="#333"
              stroke="#333"
            />
            <path
              d="M6 34L12.1195 29.4103C13.2239 28.5821 14.7509 28.6143 15.8192 29.4885L25 37"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M42 6L30 18"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
        </a>
        <a
          href="https://www.996day.com/jj.html"
          target="_blank"
          class="fab-item"
          title="音视频剪辑"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 48 48"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path d="M43 9V17V31V39H34V31H43V17H34V9H43Z" fill="none" />
            <path d="M5 17V9H14V17H5V31H14V39H5V31V17Z" fill="none" />
            <path
              d="M43 17V9H34M43 17V31M43 17H34M5 17V9H14M5 17V31M5 17H14M5 31V39H14M5 31H14M43 31V39H34M43 31H34M34 9V17M34 9H30M34 39V31M34 39H30M14 9V17M14 9H18M14 39V31M14 39H18M14 17H18M34 17H30M34 31H30M14 31H18"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M24 7V11"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <path
              d="M24 17V21"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <path
              d="M24 27V31"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
            <path
              d="M24 37V41"
              stroke="#333"
              stroke-width="4"
              stroke-linecap="round"
            />
          </svg>
        </a>
        <a
          href="https://www.996day.com/format.html"
          target="_blank"
          class="fab-item"
          title="音视频转换"
        >
          <svg
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M16 12L20 8M20 8L16 4M20 8H9M8 12L4 16M4 16L8 20M4 16H15"
              stroke="currentColor"
              stroke-width="2"
            />
          </svg>
        </a>
        <a
          href="https://www.996day.com/merge.html"
          target="_blank"
          class="fab-item"
          title="音视频合并"
        >
          <svg
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M8 12H12M16 12H12M12 12V8M12 12V16M3 9V15C3 16.6569 4.34315 18 6 18H18C19.6569 18 21 16.6569 21 15V9C21 7.34315 19.6569 6 18 6H6C4.34315 6 3 7.34315 3 9Z"
              stroke="currentColor"
              stroke-width="2"
            />
          </svg>
        </a>
      </div>
    </div>
    <div class="header">
      <h1>屏幕录制工具(移动端受权限限制,无法支持,请谅解)</h1>
      <button id="themeToggle" class="theme-toggle">深色模式</button>
    </div>

    <div class="row">
      <div class="col">
        <div class="card preview-container">
          <div class="card-title"><i>🔴</i> 预览与录制</div>
          <div class="recording-indicator">录制中...</div>
          <video id="videoPreview" controls autoplay playsinline muted></video>

          <div class="controls">
            <button id="startBtn" class="btn">
              <span class="icon record-icon"></span>开始录制
            </button>
            <button id="stopBtn" class="btn" disabled>
              <span class="icon stop-icon"></span>停止录制
            </button>
          </div>

          <div id="status" class="status">准备录制屏幕内容...</div>
        </div>
      </div>

      <div class="col">
        <div class="card recorded-video-container" id="recordedContainer">
          <div class="card-title"><i>🎬</i> 已录制的视频</div>
          <video id="recordedVideo" controls></video>

          <div class="controls">
            <button id="playBtn" class="btn">
              <span class="icon play-icon"></span>播放视频
            </button>
            <button id="downloadWebmBtn" class="btn">
              <span class="icon download-icon"></span>下载WebM
            </button>
            <!-- 添加下载为MP4的按钮 -->
            <button id="downloadMp4Btn" class="btn download-mp4-btn">
              <span class="icon download-icon"></span>下载MP4
            </button>
          </div>

          <div id="infoText" class="status" style="margin-top: 15px">
            录制已完成，可以播放或下载视频文件
          </div>
        </div>
      </div>
    </div>

    <!-- 添加录制记录面板 -->
    <div class="recordings-panel" id="recordingsPanel">
      <div class="recordings-header">
        <div class="card-title">
          <i>📼</i>
          录制记录(第一次MP4下载需要加载依赖包,请优先下载webm到本地,防止丢失)
        </div>
        <button id="clearBtn" class="clear-btn">清除所有记录</button>
      </div>

      <div class="recordings-list" id="recordingsList">
        <div class="no-recordings">暂无录制记录</div>
      </div>
    </div>

    <!-- 视频播放弹框 -->
    <div class="video-modal" id="videoModal">
      <div class="video-modal-content">
        <div class="modal-header">
          <h3 class="modal-title" id="modalVideoTitle">播放录制视频</h3>
          <button class="close-modal" id="closeModal">&times;</button>
        </div>
        <div class="modal-video-container">
          <video class="modal-video" id="modalVideo" controls></video>
        </div>
        <div class="modal-info" id="modalVideoInfo"></div>
      </div>
    </div>

    <!-- 加载覆盖层 -->
    <div class="loading-overlay" id="loadingOverlay">
      <div class="spinner"></div>
      <div id="loadingText">处理中，请稍候...</div>
    </div>

    <!-- 授权弹框 -->
    <div id="authModal" class="auth-modal">
      <div class="auth-modal-content">
        <!-- 步骤指示器 -->
        <div class="auth-step-indicator">
          <div class="step-dot active" id="step1Dot"></div>
          <div class="step-dot" id="step2Dot"></div>
        </div>

        <!-- 授权内容 -->
        <div id="authContent">
          <!-- 麦克风授权步骤 -->
          <div id="micAuthStep">
            <div class="auth-icon">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 24 24"
                fill="currentColor"
              >
                <path
                  d="M12 2a3 3 0 0 1 3 3v6a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z"
                />
                <path
                  d="M19 10v1a7 7 0 0 1-14 0v-1"
                  stroke="currentColor"
                  stroke-width="2"
                  fill="none"
                />
                <path d="M12 18v4" stroke="currentColor" stroke-width="2" />
                <path d="M8 22h8" stroke="currentColor" stroke-width="2" />
              </svg>
            </div>
            <h3 class="auth-title">麦克风权限</h3>
            <p class="auth-description">
              为了录制音频，我们需要访问您的麦克风。请在浏览器弹出的权限请求中点击"允许"。
            </p>

            <!-- macOS权限说明 -->
            <div
              class="macos-permission-notice"
              id="macosNotice"
              style="display: none"
            >
              <div class="notice-header">
                <span class="apple-icon">🍎</span>
                <strong>macOS用户注意</strong>
              </div>
              <div class="notice-content">
                <p>如果浏览器权限请求失败，请检查系统设置：</p>
                <ol>
                  <li>
                    打开 <strong>系统偏好设置</strong> →
                    <strong>安全性与隐私</strong>
                  </li>
                  <li>点击 <strong>隐私</strong> 标签页</li>
                  <li>在左侧列表中选择 <strong>麦克风</strong></li>
                  <li>确保您的浏览器（Safari/Chrome/Firefox等）已勾选</li>
                  <li>如果没有勾选，请点击左下角锁图标解锁后勾选</li>
                </ol>
                <p class="notice-tip">💡 设置完成后，请刷新页面重新尝试授权</p>
              </div>
            </div>
            <div class="auth-buttons">
              <button class="auth-btn auth-btn-secondary" id="cancelAuth">
                取消
              </button>
              <button class="auth-btn auth-btn-secondary" id="skipMicAuth">
                跳过
              </button>
              <button class="auth-btn auth-btn-primary" id="requestMicAuth">
                授权麦克风
              </button>
            </div>
          </div>

          <!-- 屏幕授权步骤 -->
          <div id="screenAuthStep" style="display: none">
            <div class="auth-icon">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 24 24"
                fill="currentColor"
              >
                <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
                <line
                  x1="8"
                  y1="21"
                  x2="16"
                  y2="21"
                  stroke="currentColor"
                  stroke-width="2"
                />
                <line
                  x1="12"
                  y1="17"
                  x2="12"
                  y2="21"
                  stroke="currentColor"
                  stroke-width="2"
                />
              </svg>
            </div>
            <h3 class="auth-title">屏幕共享权限</h3>
            <p class="auth-description">
              现在需要选择要录制的屏幕或窗口。请在接下来的对话框中选择您要录制的内容。
            </p>
            <div class="auth-buttons">
              <button class="auth-btn auth-btn-secondary" id="backToMic">
                返回
              </button>
              <button class="auth-btn auth-btn-primary" id="requestScreenAuth">
                选择屏幕
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <script>
      // 页面元素
      const videoPreview = document.getElementById('videoPreview')
      const recordedVideo = document.getElementById('recordedVideo')
      const startBtn = document.getElementById('startBtn')
      const stopBtn = document.getElementById('stopBtn')
      const playBtn = document.getElementById('playBtn')
      const downloadWebmBtn = document.getElementById('downloadWebmBtn')
      const downloadMp4Btn = document.getElementById('downloadMp4Btn')
      const themeToggle = document.getElementById('themeToggle')
      const statusDisplay = document.getElementById('status')
      const recordingIndicator = document.querySelector('.recording-indicator')
      const recordedContainer = document.getElementById('recordedContainer')
      const infoText = document.getElementById('infoText')
      const recordingsPanel = document.getElementById('recordingsPanel')
      const recordingsList = document.getElementById('recordingsList')
      const clearBtn = document.getElementById('clearBtn')
      const videoModal = document.getElementById('videoModal')
      const modalVideo = document.getElementById('modalVideo')
      const modalVideoTitle = document.getElementById('modalVideoTitle')
      const modalVideoInfo = document.getElementById('modalVideoInfo')
      const closeModal = document.getElementById('closeModal')
      const loadingOverlay = document.getElementById('loadingOverlay')
      const loadingText = document.getElementById('loadingText')

      // 授权弹框元素
      const authModal = document.getElementById('authModal')
      const micAuthStep = document.getElementById('micAuthStep')
      const screenAuthStep = document.getElementById('screenAuthStep')
      const step1Dot = document.getElementById('step1Dot')
      const step2Dot = document.getElementById('step2Dot')
      const requestMicAuth = document.getElementById('requestMicAuth')
      const requestScreenAuth = document.getElementById('requestScreenAuth')
      const cancelAuth = document.getElementById('cancelAuth')
      const backToMic = document.getElementById('backToMic')
      const skipMicAuth = document.getElementById('skipMicAuth')

      // 状态变量
      let recorder
      let recordedBlob
      let screenStream = null
      let micStream = null
      let audioCtx = null
      let combinedStream = null
      let currentRecordedUrl
      let isDarkMode = false
      let recordings = JSON.parse(
        localStorage.getItem('screenRecordings') || '[]'
      )
      let ffmpeg = null // 添加ffmpeg实例
      const { createFFmpeg, fetchFile } = FFmpeg

      // 授权状态
      const authState = {
        micAuthorized: false,
        screenAuthorized: false,
      }

      // 检测操作系统
      const isMacOS = /Mac|iPhone|iPod|iPad/i.test(navigator.userAgent)
      const macosNotice = document.getElementById('macosNotice')

      async function toBlobURL(url, mimeType) {
        const res = await fetch(url)
        const blob = await res.blob()
        return URL.createObjectURL(blob)
      }
      // 初始化FFmpeg
      async function initFFmpeg() {
        if (!ffmpeg) {
          loadingText.textContent = '正在加载FFmpeg，请稍候...'
          try {
            showLoading(true)

            ffmpeg = createFFmpeg({
              log: true,
              wasmURL: await toBlobURL(
                './ffmpeg-core.wasm',
                'application/wasm'
              ),
            })
            await ffmpeg.load()

            return ffmpeg
          } catch (error) {
            console.error('FFmpeg加载失败:', error)
            statusDisplay.textContent = 'FFmpeg加载失败: ' + error.message
          } finally {
            showLoading(false)
          }
        }
      }

      // 显示/隐藏加载层
      function showLoading(show) {
        loadingOverlay.style.display = show ? 'flex' : 'none'
      }

      // 授权弹框控制函数
      function showAuthModal() {
        authModal.style.display = 'flex'
        showMicAuthStep()
      }

      function hideAuthModal() {
        authModal.style.display = 'none'
      }

      function showMicAuthStep() {
        micAuthStep.style.display = 'block'
        screenAuthStep.style.display = 'none'
        step1Dot.classList.add('active')
        step2Dot.classList.remove('active')

        // 如果是macOS系统，显示权限说明
        if (isMacOS && macosNotice) {
          macosNotice.style.display = 'block'
        }
      }

      function showScreenAuthStep() {
        micAuthStep.style.display = 'none'
        screenAuthStep.style.display = 'block'
        step1Dot.classList.remove('active')
        step2Dot.classList.add('active')
      }

      // 更新按钮状态
      function updateButtonStates() {
        const canStart = authState.screenAuthorized

        if (canStart) {
          const audioStatus = authState.micAuthorized
            ? '(含麦克风)'
            : '(仅屏幕)'
          statusDisplay.textContent = `准备就绪，可以开始录制${audioStatus}`
        } else {
          statusDisplay.textContent = '需要授权: 屏幕共享'
        }
      }

      // 初始化记录显示
      updateRecordingsList()

      // 主题切换功能
      themeToggle.addEventListener('click', () => {
        isDarkMode = !isDarkMode
        document.body.classList.toggle('dark-theme', isDarkMode)
        themeToggle.textContent = isDarkMode ? '浅色模式' : '深色模式'
      })

      // 清除所有记录
      clearBtn.addEventListener('click', () => {
        if (confirm('确定要清除所有录制记录吗？该操作不可撤销！')) {
          // 释放所有Blob URL
          recordings.forEach((recording) => {
            URL.revokeObjectURL(recording.url)
          })

          recordings = []
          localStorage.removeItem('screenRecordings')
          updateRecordingsList()
          showPanel(false)
        }
      })

      // 关闭弹框
      closeModal.addEventListener('click', () => {
        closeVideoModal()
      })

      // 点击弹框外部区域关闭
      videoModal.addEventListener('click', (e) => {
        if (e.target === videoModal) {
          closeVideoModal()
        }
      })

      // 授权弹框事件监听器
      cancelAuth.addEventListener('click', () => {
        hideAuthModal()
      })

      backToMic.addEventListener('click', () => {
        showMicAuthStep()
      })

      requestMicAuth.addEventListener('click', async () => {
        try {
          statusDisplay.textContent = '正在请求麦克风权限...'
          micStream = await navigator.mediaDevices.getUserMedia({
            audio: {
              echoCancellation: true,
              noiseSuppression: true,
            },
          })
          authState.micAuthorized = true
          showScreenAuthStep()
          statusDisplay.textContent = '麦克风授权成功，请继续授权屏幕共享'
        } catch (error) {
          console.error('麦克风授权失败:', error)
          statusDisplay.textContent = '麦克风授权失败: ' + error.message

          // 如果是macOS系统且授权失败，显示权限说明
          if (isMacOS && macosNotice) {
            macosNotice.style.display = 'block'
          }
        }
      })

      skipMicAuth.addEventListener('click', () => {
        authState.micAuthorized = false
        micStream = null
        showScreenAuthStep()
        statusDisplay.textContent = '已跳过麦克风授权，请继续授权屏幕共享'
      })

      requestScreenAuth.addEventListener('click', async () => {
        try {
          statusDisplay.textContent = '正在请求屏幕共享权限...'
          screenStream = await navigator.mediaDevices.getDisplayMedia({
            video: {
              cursor: 'always',
              frameRate: { ideal: 60, max: 120 },
              width: { ideal: 3840, max: 7680 },
              height: { ideal: 2160, max: 4320 },
              aspectRatio: { ideal: 16 / 9 },
            },
            audio: {
              sampleRate: 48000,
              channelCount: 2,
              echoCancellation: false,
              noiseSuppression: false,
              autoGainControl: false,
            },
          })
          authState.screenAuthorized = true
          hideAuthModal()
          startRecord()
          updateButtonStates()
          statusDisplay.textContent = '所有权限授权完成，可以开始录制'
        } catch (error) {
          console.error('屏幕共享授权失败:', error)
          statusDisplay.textContent = '屏幕共享授权失败: ' + error.message
        }
      })

      // 点击授权弹框外部区域关闭
      authModal.addEventListener('click', (e) => {
        if (e.target === authModal) {
          hideAuthModal()
        }
      })

      const startRecord = async () => {
        // 检查授权状态 - 只要求屏幕授权，麦克风授权可选
        if (!authState.screenAuthorized) {
          showAuthModal()
          return
        }

        try {
          statusDisplay.textContent = '正在准备录制...'

          // 检测系统音频是否可用
          let hasSystemAudio = false
          screenStream.getAudioTracks().forEach((track) => {
            if (track.kind === 'audio' && track.readyState === 'live') {
              hasSystemAudio = true
            }
          })

          // 创建音频处理上下文
          audioCtx = new (window.AudioContext || window.webkitAudioContext)()
          const audioDestination = audioCtx.createMediaStreamDestination()

          // 智能混合系统音频和麦克风
          if (hasSystemAudio) {
            // 系统伴奏增强处理
            const systemSource = audioCtx.createMediaStreamSource(
              new MediaStream(screenStream.getAudioTracks())
            )
            const systemGain = audioCtx.createGain()
            systemGain.gain.value = micStream ? 1.5 : 1.0
            systemSource.connect(systemGain).connect(audioDestination)

            // 处理麦克风（如果已授权）
            if (micStream && authState.micAuthorized) {
              const micSource = audioCtx.createMediaStreamSource(micStream)
              const micGain = audioCtx.createGain()
              micGain.gain.value = 1.2
              micSource.connect(micGain).connect(audioDestination)
            }
          } else {
            if (micStream && authState.micAuthorized) {
              const micSource = audioCtx.createMediaStreamSource(micStream)
              micSource.connect(audioDestination)
              statusDisplay.textContent =
                '检测到系统音频不可用，仅录制麦克风音频'
            } else {
              statusDisplay.textContent = '警告：无任何音频来源，将录制无声视频'
            }
          }

          // 创建最终媒体流
          combinedStream = new MediaStream([
            ...screenStream.getVideoTracks(),
            ...audioDestination.stream.getAudioTracks(),
          ])

          // 预览和录制
          videoPreview.style.display = 'block'
          videoPreview.srcObject = combinedStream
          recordingIndicator.style.display = 'block'
          recordedContainer.style.display = 'none'

          recorder = RecordRTC(combinedStream, {
            type: 'video',
            mimeType: 'video/webm;codecs=h264,opus',
            videoBitsPerSecond: 2_500_000,
            audioBitsPerSecond: 192_000, // 提高音频比特率
            disableLogs: true,
          })
          recorder.startRecording()
          startBtn.disabled = true
          stopBtn.disabled = false

          // 根据实际音频状态显示录制信息
          let recordingStatus = '正在录制：'
          if (hasSystemAudio && micStream && authState.micAuthorized) {
            recordingStatus += '系统音频+麦克风'
          } else if (hasSystemAudio) {
            recordingStatus += '系统音频（无麦克风）'
          } else if (micStream && authState.micAuthorized) {
            recordingStatus += '麦克风（无系统音频）'
          } else {
            recordingStatus += '无声视频'
          }
          statusDisplay.textContent = recordingStatus

          // 8. 自动检测系统音频丢失
          combinedStream.getTracks().forEach(
            (t) =>
              (t.onended = () => {
                statusDisplay.textContent = '⚠️ 媒体轨道已断开!'
                setTimeout(stopRecording, 500)
              })
          )
        } catch (err) {
          console.error('录制初始化失败:', err)
          statusDisplay.textContent = `错误: ${err.name || '未知错误'}`
          resetControls()
        }
      }

      startBtn.addEventListener('click', startRecord)

      // 停止录制
      stopBtn.addEventListener('click', stopRecording)

      function stopRecording() {
        if (!recorder) return

        recorder.stopRecording(async () => {
          // 隐藏录制指示器
          recordingIndicator.style.display = 'none'

          // 获取录制的Blob
          recordedBlob = recorder.getBlob()

          // 创建视频URL并设置给播放元素
          currentRecordedUrl = URL.createObjectURL(recordedBlob)
          recordedVideo.src = currentRecordedUrl

          // 更新UI状态
          recordedContainer.style.display = 'block'
          infoText.textContent = `录制已完成，视频大小: ${formatFileSize(
            recordedBlob.size
          )}`
          statusDisplay.textContent = '录制完成!'

          // 添加录制记录
          addRecording({
            blob: recordedBlob,
            size: recordedBlob.size,
            timestamp: new Date(),
          })

          // 1. 停止combinedStream
          if (combinedStream) {
            combinedStream.getTracks().forEach((t) => t.stop())
            combinedStream = null
          }

          // 2. 停止屏幕流并重置屏幕授权状态
          if (screenStream) {
            screenStream.getTracks().forEach((t) => t.stop())
            screenStream = null
          }
          authState.screenAuthorized = false

          // 3. 停止麦克风并重置麦克风授权状态
          if (micStream) {
            micStream.getTracks().forEach((t) => t.stop())
            micStream = null
          }
          authState.micAuthorized = false
          // 4. 关闭音频上下文
          if (audioCtx) {
            await audioCtx.close()
            audioCtx = null
          }

          videoPreview.srcObject = null
          videoPreview.style.display = 'none'

          // 重置控制按钮状态
          resetControls()

          // 更新按钮状态
          updateButtonStates()

          // 显示录制历史面板
          showPanel(true)
        })
      }

      // 格式化文件大小
      function formatFileSize(bytes) {
        if (bytes < 1024) return bytes + ' B'
        else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'
        else return (bytes / 1048576).toFixed(1) + ' MB'
      }

      // 添加录制记录
      function addRecording(recordingData) {
        // 生成唯一ID用于管理记录
        const id = Date.now()

        // 创建Blob URL
        recordingData.url = URL.createObjectURL(recordingData.blob)
        recordingData.id = id
        recordingData.title = `录制_${new Date(id)
          .toLocaleString()
          .replace(/[:]/g, '-')}`

        // 添加到记录数组
        recordings.unshift(recordingData)

        // 保存到localStorage（最大保存10个）
        if (recordings.length > 10) {
          // 释放最旧记录的Blob URL
          URL.revokeObjectURL(recordings[recordings.length - 1].url)
          recordings.pop() // 删除最旧的记录
        }
        localStorage.setItem('screenRecordings', JSON.stringify(recordings))

        // 更新UI
        updateRecordingsList()
      }

      // 更新记录列表
      function updateRecordingsList() {
        if (recordings.length === 0) {
          recordingsList.innerHTML = `<div class="no-recordings">暂无录制记录</div>`
          return
        }

        recordingsList.innerHTML = ''

        recordings.forEach((recording) => {
          const formattedDate = new Date(recording.id).toLocaleString()
          const formattedSize = formatFileSize(recording.size)

          const recordingEl = document.createElement('div')
          recordingEl.className = 'recording-item'
          recordingEl.dataset.id = recording.id

          recordingEl.innerHTML = `
            <div class="recording-info">
              <div class="recording-title">${recording.title}</div>
              <div class="recording-meta">
                <span>${formattedSize}</span>
                <span>${formattedDate}</span>
              </div>
            </div>
            <div class="recording-controls">
              <button class="recording-btn play-btn">
                <i class="play-icon"></i>播放
              </button>
              <button class="recording-btn download-btn">
                <i class="download-icon"></i>WebM
              </button>
              <button class="recording-btn download-mp4-btn">
                <i class="download-icon"></i>MP4
              </button>
              <button class="recording-btn delete-btn">
                <i class="delete-icon">×</i>删除
              </button>
            </div>
          `

          // 添加播放事件 - 在弹框中播放
          recordingEl
            .querySelector('.play-btn')
            .addEventListener('click', () => {
              playRecordingInModal(recording.id)
            })

          // 添加webm下载事件
          recordingEl
            .querySelector('.download-btn')
            .addEventListener('click', () => {
              downloadWebm(recording.id)
            })

          // 添加mp4下载事件
          recordingEl
            .querySelector('.download-mp4-btn')
            .addEventListener('click', async () => {
              await downloadRecordingAsMp4(recording.id)
            })

          // 添加删除事件
          recordingEl
            .querySelector('.delete-btn')
            .addEventListener('click', () => {
              deleteRecording(recording.id)
            })

          recordingsList.appendChild(recordingEl)
        })
      }

      // 在弹框中播放记录
      function playRecordingInModal(id) {
        const recording = recordings.find((r) => r.id == id)
        if (!recording) return

        // 设置弹框内容
        modalVideoTitle.textContent = recording.title
        modalVideoInfo.textContent = `文件大小: ${formatFileSize(
          recording.size
        )} | 录制时间: ${new Date(recording.id).toLocaleString()}`
        modalVideo.src = recording.url

        // 打开弹框
        openVideoModal()
      }

      // 打开视频弹框
      function openVideoModal() {
        videoModal.style.display = 'flex'
        // 开始播放
        setTimeout(() => {
          modalVideo.play().catch((e) => console.error('播放失败:', e))
        }, 300)
      }

      // 关闭视频弹框
      function closeVideoModal() {
        modalVideo.pause()
        videoModal.style.display = 'none'
        modalVideo.src = ''
      }

      // 下载指定记录为webm
      function downloadWebm(id) {
        const recording = recordings.find((r) => r.id == id)

        if (!recording) return

        const a = document.createElement('a')
        a.href = recording.url
        a.download = `${recording.title}.webm`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      }

      // 下载指定记录为mp4
      async function downloadRecordingAsMp4(id) {
        const recording = recordings.find((r) => r.id == id)
        if (!recording) return

        try {
          loadingText.textContent = '正在转换格式，请稍候...'
          showLoading(true)

          await initFFmpeg()

          const { createFFmpeg, fetchFile } = FFmpeg
          // 将Blob写入FFmpeg的文件系统
          ffmpeg.FS('writeFile', 'input.webm', await fetchFile(recording.blob))

          // 运行FFmpeg转换命令
          await ffmpeg.run(
            '-i',
            'input.webm',
            '-c:v',
            'copy',
            '-c:a',
            'aac',
            'output.mp4'
          )

          // 读取转换结果
          const data = ffmpeg.FS('readFile', 'output.mp4')
          const mp4Blob = new Blob([data.buffer], { type: 'video/mp4' })
          const mp4Url = URL.createObjectURL(mp4Blob)

          // 创建下载链接
          const a = document.createElement('a')
          a.href = mp4Url
          a.download = `${recording.title}.mp4`
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)

          // 清理资源
          setTimeout(() => {
            URL.revokeObjectURL(mp4Url)
            // 清理FFmpeg文件系统
            ffmpeg.FS('unlink', 'input.webm')
            ffmpeg.FS('unlink', 'output.mp4')
          }, 3000)

          statusDisplay.textContent = 'MP4格式转换完成，文件开始下载'
        } catch (error) {
          console.error('转换失败:', error)
          statusDisplay.textContent = `转换失败: ${error.message}`
        } finally {
          showLoading(false)
        }
      }

      // 下载最新录制为MP4
      downloadMp4Btn.addEventListener('click', async () => {
        if (!recordedBlob) return

        try {
          loadingText.textContent = '正在转换格式，请稍候...'
          showLoading(true)
          const { createFFmpeg, fetchFile } = FFmpeg

          await initFFmpeg()

          // 将Blob写入FFmpeg的文件系统
          ffmpeg.FS('writeFile', 'input.webm', await fetchFile(recordedBlob))

          // 运行FFmpeg转换命令
          await ffmpeg.run(
            '-i',
            'input.webm',
            '-c:v',
            'copy',
            '-c:a',
            'aac',
            'output.mp4'
          )

          // 读取转换结果
          const data = ffmpeg.FS('readFile', 'output.mp4')
          const mp4Blob = new Blob([data.buffer], { type: 'video/mp4' })
          const mp4Url = URL.createObjectURL(mp4Blob)
          const fileName = `录制_${new Date()
            .toISOString()
            .replace(/[:.]/g, '-')}.mp4`

          // 创建下载链接
          const a = document.createElement('a')
          a.href = mp4Url
          a.download = fileName
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)

          infoText.textContent = 'MP4格式转换完成，文件开始下载...'

          // 清理资源
          setTimeout(() => {
            URL.revokeObjectURL(mp4Url)
            // 清理FFmpeg文件系统
            ffmpeg.FS('unlink', 'input.webm')
            ffmpeg.FS('unlink', 'output.mp4')
            infoText.textContent = `下载完成! MP4文件大小: ${formatFileSize(
              mp4Blob.size
            )}`
          }, 3000)
        } catch (error) {
          console.error('转换失败:', error)
          statusDisplay.textContent = `转换失败: ${error.message}`
        } finally {
          showLoading(false)
        }
      })

      // 下载最新录制为WebM
      downloadWebmBtn.addEventListener('click', () => {
        if (!recordedBlob) return

        const fileName = `录制_${new Date()
          .toISOString()
          .replace(/[:.]/g, '-')}.webm`
        const url = URL.createObjectURL(recordedBlob)
        const a = document.createElement('a')
        a.href = url
        a.download = fileName
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        infoText.textContent = '文件开始下载，正在清理资源...'

        // 清理资源
        setTimeout(() => {
          URL.revokeObjectURL(url)
          infoText.textContent = `下载完成! WebM文件大小: ${formatFileSize(
            recordedBlob.size
          )}`
        }, 3000)
      })

      // 删除单条记录
      function deleteRecording(id) {
        // 查找记录
        const recordingIndex = recordings.findIndex((r) => r.id == id)
        if (recordingIndex === -1) return

        // 释放资源
        URL.revokeObjectURL(recordings[recordingIndex].url)

        // 如果删除的记录正在播放，关闭弹框
        if (modalVideo.src.includes(id)) {
          closeVideoModal()
        }

        // 从数组中移除
        recordings.splice(recordingIndex, 1)

        // 更新存储
        localStorage.setItem('screenRecordings', JSON.stringify(recordings))

        // 更新UI
        updateRecordingsList()

        // 如果没有记录了则隐藏面板
        if (recordings.length === 0) {
          showPanel(false)
        }
      }

      // 显示/隐藏录制面板
      function showPanel(show) {
        recordingsPanel.style.display = show ? 'block' : 'none'
      }

      // 播放最新录制在弹框中
      playBtn.addEventListener('click', () => {
        if (!recordedBlob) return

        // 设置弹框内容
        const title = `最近录制_${new Date()
          .toLocaleString()
          .replace(/[:]/g, '-')}`
        modalVideoTitle.textContent = title
        modalVideoInfo.textContent = `文件大小: ${formatFileSize(
          recordedBlob.size
        )}`
        modalVideo.src = currentRecordedUrl

        // 打开弹框
        openVideoModal()
      })

      // 重置控制按钮状态
      function resetControls() {
        startBtn.disabled = false
        stopBtn.disabled = true
      }

      // 如果有记录，显示面板
      if (recordings.length > 0) {
        showPanel(true)
      }

      window.addEventListener('unload', () => {
        // 释放所有Blob URL
        recordings.forEach((recording) => {
          URL.revokeObjectURL(recording.url)
        })

        recordings = []
        localStorage.removeItem('screenRecordings')
        updateRecordingsList()
        showPanel(false)
      })
      // 浮动按钮交互
      document.addEventListener('DOMContentLoaded', () => {
        const fabContainer = document.querySelector('.fab-container')
        const fabMain = document.getElementById('fabMain')

        fabMain.addEventListener('click', () => {
          fabContainer.classList.toggle('active')
        })

        // 点击页面其他地方关闭菜单
        document.addEventListener('click', (e) => {
          if (!fabContainer.contains(e.target)) {
            fabContainer.classList.remove('active')
          }
        })

        // 初始化按钮状态
        updateButtonStates()
      })
    </script>
    <script src="./title.js"></script>
  </body>
</html>
